/* Copyright (c) 2009 Christopher Humphries, Maxime Simon
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package userinterface;

import history.Caretaker;
import history.Originator;

import java.awt.BorderLayout;
import java.awt.Insets;
import java.awt.Scrollbar;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSlider;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import javax.swing.JToolBar;
import javax.swing.JTree;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingConstants;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.TreeSelectionModel;

import data.Buffer;

/**
 * @author Humphries Christopher - Simon Maxime
 * 
 */
public class GraphicalInterface extends JFrame implements ChangeListener {

    private static final long serialVersionUID = 1L;

    protected JFileChooser m_fileChooser;
    private JToolBar m_toolBar, m_macroToolBar;
    protected JButton m_buttonInfo, m_buttonNew, m_buttonOpen, m_buttonSave;
    protected JButton m_macroButtonToggle, m_macroButtonRun, m_macroButtonAdd,
	    m_macroButtonAccept, m_macroButtonDelete, m_macroButtonDiscard;

    private JPanel m_historyPanel;
    private JScrollPane m_textPane;
    protected JScrollPane m_macroScrollPane;

    protected JTextArea m_textArea;
    private BorderLayout m_historyLayout;
    protected JSlider m_historySlider;
    private JLabel m_historyLabel;

    protected JTree m_macroTree;

    protected JSplitPane m_splitPane;

    private Buffer m_buffer;
    private Caretaker m_caretaker;
    private Originator m_originator;

    private boolean m_sliderEventsLocked;
    private int m_currentIndex;
    protected DefaultMutableTreeNode m_macroTreeRoot;
    private DefaultTreeCellRenderer m_renderer;

    /**
     * @param message
     */
    public void showErrorMsg(String message) {
	JOptionPane.showMessageDialog(m_textArea, message, "TildEditor",
		JOptionPane.ERROR_MESSAGE);
    }

    /**
     * 
     */
    public void updateHistBar() {
	m_sliderEventsLocked = true;

	if (!m_historySlider.isEnabled()) {
	    m_historySlider.setEnabled(true);
	}

	m_historySlider.setMaximum(m_caretaker.getCurrentIndex());
	m_historySlider.setValue(m_historySlider.getMaximum());
	m_historyLabel.setText(Integer.toString(m_historySlider.getMaximum()));
	m_currentIndex = m_caretaker.getCurrentIndex();
	updateHistLabels();
	m_sliderEventsLocked = false;
    }

    public void resetHistory() {
	m_historySlider.setEnabled(false);
	m_historySlider.setMajorTickSpacing(10);
	m_historySlider.setValue(0);
	m_historySlider.setMaximum(0);
	m_historyLabel.setText("0");
	m_historySlider.setEnabled(true);
    }

    public void resetText(String txt) {
	m_historySlider.removeChangeListener(this);
	m_historySlider.setEnabled(false);
	m_textArea.setText(txt);
	m_historySlider.setValue(0);
	m_historySlider.setMaximum(0);
	m_historyLabel.setText("0");
	m_historySlider.addChangeListener(this);
    }

    /**
    *
    */
    protected void updateHistLabels() {
	if ((m_caretaker.getCurrentIndex() + 1) % 100 == 0) {
	    m_historySlider.createStandardLabels((m_caretaker.getCurrentIndex() + 1) / 10 * 2);
	}
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * javax.swing.event.ChangeListener#stateChanged(javax.swing.event.ChangeEvent
     * )
     */
    public void stateChanged(ChangeEvent e) {
	if (!m_sliderEventsLocked) {

	    int step = -1;

	    if (m_currentIndex < m_historySlider.getValue()) {
		step = 1;
	    }

	    m_historySlider.setEnabled(false);

	    while (m_currentIndex != m_historySlider.getValue()) {
		m_historyLabel.setText(Integer.toString(m_historySlider.getValue()));

		if (step == -1) {
		    if (m_buffer.undoMemento(m_historySlider.getValue() + 1)) {
			if (m_originator.getStart() == m_originator.getEnd()) {
			    try {
				m_textArea.replaceRange(
					"",
					m_originator.getStart(),
					m_originator.getStart()
						+ m_originator.getAfter().length());
			    } catch (IllegalArgumentException exc) {
			    }
			} else {
			    m_textArea.replaceRange(m_originator.getBefore(),
				    m_originator.getStart(),
				    m_originator.getStart()
					    + m_originator.getAfter().length());
			}
		    }
		} else {
		    if (m_buffer.restoreMemento(m_historySlider.getValue())) {
			if (m_originator.getStart() == m_originator.getEnd()
				|| m_originator.getBefore().equals("")) {
			    m_textArea.insert(m_originator.getAfter(),
				    m_originator.getStart());
			} else {
			    try {
				m_textArea.replaceRange(
					m_originator.getAfter(),
					m_originator.getStart(),
					m_originator.getEnd());
			    } catch (IllegalArgumentException el) {
				System.out.println("Situation");
				System.out.println("Memento:"
					+ m_originator.getStart() + ":"
					+ m_originator.getEnd() + ":"
					+ m_originator.getBefore() + ":"
					+ m_originator.getAfter());
				System.out.println("TextAreaLength:"
					+ m_textArea.getText().length());
				System.out.println("BufferLength:"
					+ m_buffer.read().length());
			    }
			}
		    }
		}

		m_currentIndex += step;
	    }

	    m_historySlider.setEnabled(true);
	}
    }

    /**
     * 
     */
    public void reloadText() {
	m_textArea.setText(m_buffer.read());
	updateHistBar();
    }

    /**
     * @param buffer
     * @param originator
     * @param caretaker
     */
    public GraphicalInterface(Buffer buffer, Originator originator,
	    Caretaker caretaker) {
	setTitle("~Editor");
	setIconImage(new ImageIcon("images/tildicon.png").getImage());
	setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	setSize(600, 650);
	setLocationRelativeTo(null);
	setLayout(new BorderLayout());

	m_buffer = buffer;
	m_caretaker = caretaker;
	m_originator = originator;

	m_fileChooser = new JFileChooser();

	m_buttonInfo = new JButton();
	m_buttonNew = new JButton();
	m_buttonOpen = new JButton();
	m_buttonSave = new JButton();

	m_toolBar = new JToolBar();
	m_toolBar.setFloatable(false);
	m_toolBar.add(m_buttonInfo);
	m_toolBar.add(m_buttonNew);
	m_toolBar.add(m_buttonOpen);
	m_toolBar.add(m_buttonSave);

	m_renderer = new DefaultTreeCellRenderer();
	m_renderer.setClosedIcon(new ImageIcon("images/script_gear.png"));
	m_renderer.setOpenIcon(new ImageIcon("images/script_gear.png"));
	m_renderer.setLeafIcon(new ImageIcon("images/bullet_green.png"));

	m_macroTreeRoot = new DefaultMutableTreeNode("Macros");
	m_macroTree = new JTree(m_macroTreeRoot);
	m_macroTree.setCellRenderer(m_renderer);
	m_macroTree.setEditable(true);
	m_macroTree.getSelectionModel().setSelectionMode(
		TreeSelectionModel.SINGLE_TREE_SELECTION);
	m_macroTree.setShowsRootHandles(true);
	m_macroTree.setScrollsOnExpand(true);

	m_macroButtonRun = new JButton();
	m_macroButtonAdd = new JButton();
	m_macroButtonAccept = new JButton();
	m_macroButtonDelete = new JButton();
	m_macroButtonDiscard = new JButton();
	m_macroButtonToggle = new JButton();

	m_macroButtonRun.setVisible(false);
	m_macroButtonAccept.setVisible(false);
	m_macroButtonDelete.setVisible(false);
	m_macroButtonDiscard.setVisible(false);

	m_macroToolBar = new JToolBar(SwingConstants.VERTICAL);
	m_macroToolBar.setFloatable(false);
	m_macroToolBar.add(m_macroButtonToggle);
	m_macroToolBar.add(m_macroButtonAdd);
	m_macroToolBar.add(m_macroButtonAccept);
	m_macroToolBar.add(m_macroButtonDelete);
	m_macroToolBar.add(m_macroButtonDiscard);
	m_macroToolBar.add(m_macroButtonRun);

	m_macroScrollPane = new JScrollPane(m_macroTree,
		ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
		ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);

	m_textArea = new JTextArea();
	m_textArea.setText(buffer.read());
	m_textArea.setMargin(new Insets(10, 10, 10, 10));

	m_textPane = new JScrollPane(m_textArea,
		ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
		ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);

	m_historyLabel = new JLabel("0");
	m_historySlider = new JSlider(Scrollbar.HORIZONTAL, 0, 0, 0);
	m_historySlider.setMinorTickSpacing(1);
	m_historySlider.setMajorTickSpacing(10);
	m_historySlider.setPaintTicks(true);
	m_historySlider.setPaintLabels(true);
	m_historySlider.setSnapToTicks(true);
	m_historySlider.addChangeListener(this);
	m_historySlider.setEnabled(false);
	m_sliderEventsLocked = false;

	m_splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
		m_macroScrollPane, m_textPane);
	m_macroScrollPane.setVisible(false);
	m_splitPane.setBorder(null);
	m_splitPane.setDividerSize(0);
	m_splitPane.setEnabled(false);

	m_historyLayout = new BorderLayout(5, 3);
	m_historyPanel = new JPanel(m_historyLayout);
	m_historyPanel.add("West", m_historyLabel);
	m_historyPanel.add("Center", m_historySlider);

	add("North", m_toolBar);
	add("West", m_macroToolBar);
	add("Center", m_splitPane);
	add("South", m_historyPanel);
    }
}
